// 自己实现一个练练，后续写的话，我还是用c++17的
#include <iostream>
#include <typeinfo>
#include <cassert>
#include <unistd.h>
#include <any>

class Any
{
private:
    class holder
    {
    public:
        virtual ~holder() {};
        virtual const std::type_info &type() = 0; // 纯虚函数，必须重写
        virtual holder* clone() = 0;
    };

    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T& val)
            :_val(val)
        {}

        //获取类型
        virtual const std::type_info& type()
        {
            return typeid(T);
        }

        //根据当前对象自身，克隆出一个新的子类
        virtual holder* clone()
        {
            return new placeholder(_val);
        }

        T _val;
    };

    holder* _content;

public:
    Any()
    :_content(nullptr)
    {}

    template<class T>
    Any(const T& val)
        :_content(new placeholder<T>(val))
    {}

    Any(const Any& other)
        :_content(other._content ? other._content->clone() : nullptr)
    {}

    ~Any()
    {
        delete _content;
    }

    Any& swap(Any& other)
    {
        std::swap(_content,other._content);
        return *this;
    }

    //返回子类对象保存数据的指针
    template<class T>
    T* get()
    {
        assert(typeid(T) == _content->type());
        return &((placeholder<T>*)_content)->_val;
    }

    //赋值运算符重载
    template<class T>
    Any& operator=(const T& val)
    {
        Any(val).swap(*this);
        return *this;
    }

    Any& operator=(const Any& other)
    {
        Any(other).swap(*this);
        return *this;
    }
};

class Test
{
public:
    Test()
    {
        std::cout << "构造" << std::endl;
    }
    Test(const Test& other)
    {
        std::cout << "拷贝" << std::endl;
    }
    ~Test()
    {
        std::cout << "析构" << std::endl;
    }
};

int main()
{

    // Any a;
    // a = 10;

    // int* p1 = a.get<int>();
    // std::cout << *p1 << std::endl;

    // a = std::string("nihao");
    // std::string* p2 = a.get<std::string>();
    // std::cout << *p2 << std::endl;

    std::any a;
    a = 10;
    int* p1 = std::any_cast<int>(&a);
    std::cout << *p1 << std::endl;

    a = std::string("hello");

    std::string* p2 = std::any_cast<std::string>(&a);
    std::cout << *p2 << std::endl;
    
 
    return 0;
}